From 84d73a7fa55c13ed797b2b2f6cfb9071dceac800 Mon Sep 17 00:00:00 2001
From: Andrew Eikum <aeikum@codeweavers.com>
Date: Mon, 21 Oct 2019 15:30:33 -0500
Subject: [PATCH] wined3d: Use dxvk_config library to load DXVK options

---
 dlls/wined3d/directx.c | 56 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 12b53f75774..6f132ea047a 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -1326,11 +1326,44 @@ HRESULT CDECL wined3d_set_adapter_display_mode(struct wined3d *wined3d,
     return WINED3D_OK;
 }
 
+/* from dxvk_config.h, not available at wine build time in Proton */
+struct DXVKOptions {
+    int32_t customVendorId;
+    int32_t customDeviceId;
+    int32_t nvapiHack;
+};
+static HRESULT (WINAPI *pDXVKGetOptions)(struct DXVKOptions *out_opts);
+static HMODULE dxvk_config_mod;
+
+static BOOL WINAPI load_dxvk_config(INIT_ONCE *once, void *param, void **context)
+{
+    dxvk_config_mod = LoadLibraryA("dxvk_config.dll");
+    if(!dxvk_config_mod)
+    {
+        ERR_(winediag)("Couldn't load dxvk_config.dll, won't apply default DXVK config options\n");
+        return TRUE;
+    }
+
+    pDXVKGetOptions = (void*)GetProcAddress(dxvk_config_mod, "DXVKGetOptions");
+    if(!pDXVKGetOptions)
+    {
+        ERR_(winediag)("dxvk_config doesn't have DXVKGetOptions?!\n");
+        return TRUE;
+    }
+
+    return TRUE;
+}
+
 HRESULT CDECL wined3d_adapter_get_identifier(const struct wined3d_adapter *adapter,
         DWORD flags, struct wined3d_adapter_identifier *identifier)
 {
+    static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
+    struct DXVKOptions dxvk_opts;
+
     TRACE("adapter %p, flags %#x, identifier %p.\n", adapter, flags, identifier);
 
+    InitOnceExecuteOnce(&init_once, load_dxvk_config, NULL, NULL);
+
     wined3d_mutex_lock();
 
     wined3d_copy_name(identifier->driver, adapter->driver_info.name, identifier->driver_size);
@@ -1359,6 +1391,30 @@ HRESULT CDECL wined3d_get_adapter_identifier(const struct wined3d *wined3d,
     identifier->driver_version.u.LowPart = adapter->driver_info.version_low;
     identifier->vendor_id = adapter->driver_info.vendor;
     identifier->device_id = adapter->driver_info.device;
+
+    if(pDXVKGetOptions && pDXVKGetOptions(&dxvk_opts) == S_OK)
+    {
+        TRACE("got dxvk options:\n");
+        TRACE("\tnvapiHack: %u\n", dxvk_opts.nvapiHack);
+        TRACE("\tcustomVendorId: 0x%04x\n", dxvk_opts.customVendorId);
+        TRACE("\tcustomDeviceId: 0x%04x\n", dxvk_opts.customDeviceId);
+
+        /* logic from dxvk/src/dxgi/dxgi_adapter.cpp:DxgiAdapter::GetDesc2 */
+        if (dxvk_opts.customVendorId >= 0)
+            identifier->vendor_id = dxvk_opts.customVendorId;
+
+        if (dxvk_opts.customDeviceId >= 0)
+            identifier->device_id = dxvk_opts.customDeviceId;
+
+        if (dxvk_opts.customVendorId < 0 && dxvk_opts.customDeviceId < 0 &&
+                dxvk_opts.nvapiHack && adapter->driver_info.vendor == HW_VENDOR_NVIDIA) {
+            TRACE("NvAPI workaround enabled, reporting AMD GPU\n");
+            identifier->vendor_id = HW_VENDOR_AMD;
+            identifier->device_id = CARD_AMD_RADEON_RX_480;
+        }
+    }else
+        WARN("failed to get DXVK options!\n");
+
     identifier->subsystem_id = 0;
     identifier->revision = 0;
     identifier->device_identifier = IID_D3DDEVICE_D3DUID;
 
